#include "Arduino.h"
#include "SoftwareSerial.h"
#include "DFRobotDFPlayerMini.h"
#include <Ticker.h>
#include <ESP8266WiFi.h>
#include <ESP8266_Seniverse.h>
#include <TimeLib.h>
#include <WiFiUdp.h>
#include <U8g2lib.h>
#include <FS.h>
#include <bc_key_scan.h>

// #define WATCHDOG_TIMEOUT 20000

#define Sunny 1
#define Cloudy 3
#define Small_Rain 4
#define Moderate_Rain 5
#define Heavy_Rain 6
#define Wind 7

// KEY VALUE
#define NEXT 14
#define PREVIOUS 3
#define PAUSE_CONTINUE 9
#define ADD_VOLUME 0
#define SUB_VOLUME 1
#define ADD_CATOGORY 7
#define SUB_CATOGORY 8
#define POWER 15
#define TIME 12
#define WEATHER_0 13
#define WEATHER_1 2
#define WEATHER_2 6

#define power_control D5
#define k_detact D6

#define today 0
#define tommorow 1
#define third_day 2
volatile unsigned int broadcastgap = 400; // unit ms

#define folder_num_max 3
#define attachwifigap 30

typedef struct
{
  int code_day;
  int code_night;
  int high;
  int low;
  int wind_direction;
  int rain;
  int wind_scale;
} Weaday; // 天气信息的结构体
typedef struct
{
  int day;
  int month;
  int year;
  int min;
  int sec;
  int hour;
} Time;
Time time_now;
Weaday wea[3] = {}; // 定义一个weaday类型的数组存放三天的天气信息

WiFiUDP Udp;

SoftwareSerial mySoftwareSerial(D3, D4); // RX, TX
SoftwareSerial swSerial(k_detact, D7);   // creating SoftwareSerial instance, using pin 5 as Rx, 12 as Tx (Tx not used in this example)
BcKeyScan Keypad(swSerial);              // creating BcKeyScan instance using software serial port swSerial
DFRobotDFPlayerMini myDFPlayer;
Ticker timer;
Forecast forecast; // 建立Forecast对象用于获取心知天气信息
U8G2_SSD1306_128X32_UNIVISION_F_HW_I2C u8g2(U8G2_R0);

const char *ssid = "zhouliangan44";      // 连接WiFi名（此处使用taichi-maker为示例）                                       // 请将您需要连接的WiFi名填入引号中
const char *password = "wxg13948532823"; // 连接WiFi密码（此处使用12345678为示例）
String reqUserKey = "Sm-upJQVD8tXDHcDR"; // 私钥
String reqLocation = "Huhehaote";        // 城市
String reqUnit = "c";
static const char ntpServerName[] = "ntp1.aliyun.com";
const int timeZone = 8; // Central European Time
unsigned int localPort = 8888;

uint8_t key_code = 100;

time_t prevDisplay = 0; // when the digital clock was displayed
uint8_t folder_playing = 3;
uint8_t document_playing = 1;
uint8_t folder_cash = folder_playing;
uint8_t document_cash = document_playing;
uint8_t volume = 10;
uint8_t current_play_min;
uint8_t current_play_sec;

uint8_t state;      // 0-playmusic 1-timebroadcast 2-weatherbroadcast
uint8_t oled_state; // 0-播放+天气 1-播放+汉字2-播放+日期3-时间+天气4-时间+汉字5-时间+日期6-天气
bool wifi_state = 0;
bool pause = 0;
bool loop_state = 1; // 1 is enable loop
bool power = 1;
uint8_t weather_to_broadcast = 0;

// Some store parameter
uint8_t folder2_lastplayed_document = 0;
uint8_t folder3_lastplayed_document = 0;

#include "weather.h"
#include "oled.h"
#include "voicebroadast.h"
#include "play.h"
#include "basic.h"

void setup()
{
  Serial.begin(115200);
  key_init();
  pinMode(power_control, OUTPUT);
  digitalWrite(power_control, power);

  if (power)
  {
    u8g2.begin();
    u8g2.drawXBMP(0, 0, 128, 64, boot2);
    u8g2.sendBuffer();
  }
  timer.attach_ms(1000, timerISR); // 定时器中断1s
  if (SPIFFS.begin())
  { // 启动闪存文件系统
    Serial.println("SPIFFS Started.");
  }
  else
  {
    Serial.println("SPIFFS Failed to Start.");
  }

  File file = SPIFFS.open("palyparamer/data.txt", "r");
  if (!file)
  {
    Serial.println("无法打开文件！");
  }
  folder_playing = file.readStringUntil('\n').toInt();
  folder2_lastplayed_document = file.readStringUntil('\n').toInt();
  folder3_lastplayed_document = file.readStringUntil('\n').toInt();
  file.close();

  Serial.printf("folder：%d\n", folder_playing);
  Serial.printf("folder2上次播放：%d\n", folder2_lastplayed_document);
  Serial.printf("folder3上次播放：%d\n", folder3_lastplayed_document);

  if (power)
    connectWiFi();
  if (wifi_state && power)
  {
    forecast.config(reqUserKey, reqLocation, reqUnit); // 配置心知天气请求信息
    // wifi连接成功后就获取最新天气信息
    if (getweainfo())
    {
      Serial.println(" ");
      Serial.println("Get weather information successfully");

      Udp.begin(localPort);
      setSyncProvider(getNtpTime);
      setSyncInterval(300); // every 300 s get time
      // 启动查询时间---查询时需调用now()
      while (time_now.day == 0)
      {
        setSyncProvider(getNtpTime);
        gettime();
      }
    }
  }
  else
  {
    // do nothing but if need  could add cmmonds
  }
  if (power)
  {
    mySoftwareSerial.begin(9600);
    dfplayerinit();
    // weather_broadcast_oleddisplay(0);
  }
}

void loop()
{
  key_detaction();

  state_switch();
  detactwifi();

  if (Serial.available())
  {

    String data = Serial.readString();
    int i = data.toInt();
    // myDFPlayer.play(i);  //Play the first mp3
    // Serial.println(i);

    key_code = i;
    Serial.println(key_code);
  }

  if (myDFPlayer.available() && power)
  {
    printDetail(myDFPlayer.readType(), myDFPlayer.read()); // Print the detail message from DFPlayer to handle different errors and states.
  }
}
